<template>
  <el-form
    ref="formRef"
    class="query-form"
    :inline="inline"
    :label-position="labelPosition"
    :label-width="labelWidth"
    :model="state.form"
    :size="size"
  >
    <el-row :gutter="20">
      <el-col v-for="field in visibleFields" :key="field.prop" :span="field.colSpan || 6">
        <el-form-item :label="field.label" :prop="field.prop" :rules="field.rules">
          <component
            :is="field.component"
            v-model="state.form[field.prop]"
            v-bind="field.componentProps || {}"
            :disabled="field.disabled"
            :options="field.options"
            :placeholder="field.placeholder"
          />
        </el-form-item>
      </el-col>
    </el-row>
    <el-form-item>
      <el-button :loading="state.loading" type="primary" @click="handleSearch">查询</el-button>
      <el-button @click="handleReset">重置</el-button>
    </el-form-item>
  </el-form>
</template>

<script setup lang="ts">
import type { FormInstance } from 'element-plus'
import { computed, ref, watch } from 'vue'
import { useQueryForm } from './hooks/useQueryForm'
import type { QueryFormEvents, QueryFormOptions } from './types'

const props = withDefaults(defineProps<QueryFormOptions>(), {
  inline: true,
  labelWidth: '100px',
  labelPosition: 'right',
  size: 'default',
})

const emit = defineEmits<QueryFormEvents>()

const formRef = ref<FormInstance>()
const { state, resetForm, setForm, setLoading } = useQueryForm(props.fields)

// 可见字段
const visibleFields = computed(() => {
  return props.fields.filter((field) => field.visible !== false)
})

// 监听 loading 状态
watch(
  () => props.loading,
  (val) => {
    setLoading(val)
  }
)

// 监听表单数据变化
watch(
  () => state.form,
  (val) => {
    emit('form-change', val)
  },
  { deep: true }
)

// 查询
const handleSearch = () => {
  emit('search', state.form)
}

// 重置
const handleReset = () => {
  resetForm()
  emit('reset')
}

// 暴露方法
defineExpose({
  formRef,
  setForm,
  resetForm,
})
</script>

<style scoped>
.query-form {
  padding: 20px;
  background-color: #fff;
  border-radius: 4px;
}
</style>
